﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using XMLCharSheets;

namespace CombatAutomationTheater
{
    internal class CharacterCreationViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<CharacterSheet> FilteredCharacters = new ObservableCollection<CharacterSheet>();

        public CharacterCreationViewModel()
        {
            ResetActiveList();
            CombatService.RosterViewModel.RulesetSelected += RulesetSelected;
            AvailableSystems.Add(_placeholderSystem);
            foreach (var cur in CombatService.RosterViewModel.SystemConstants)
            {
                AvailableSystems.Add(cur);
            }
            CurrentSystemFilter = AvailableSystems.FirstOrDefault(x=>x.SystemIDProperty.Equals(MainConfigurationSettingsViewModel.Instance.SystemFilter));
        }

        private void RulesetSelected(object sender, RulesetSelectedEventArgs e)
        {
            var prevSelected = SelectedNewCharacter;
            if (e.SelectedRuleset != CurrentSystemFilter.SystemIDProperty)
            {
                ResetBaseList();
                ResetActiveList();
            }
            if (FilteredCharacters.Contains(prevSelected))
            {
                SelectedNewCharacter = prevSelected;
            }
            SystemNotChosen = false;
            if (e.SelectedRuleset == RulesetSelectedEventArgs.ClearRulesetString)
            {
                CurrentSystemFilter = _placeholderSystem;
                SystemNotChosen = true;
            }
            else
            {
                CurrentSystemFilter = AvailableSystems.First(x=>x.SystemIDProperty.Equals(e.SelectedRuleset));
            }
        }

        //Used to repopulate the list after a system selection changes (as in from opening from one system to another);
        private void ResetBaseList()
        {
            
            

        }

        public ISystemConstants CurrentSystemFilter
        {
            get { return _currentSystemFilter; }
            set 
            {
                _currentSystemFilter = value; 
                OnPropertyChanged("CurrentSystemFilter");
                SearchForText();
                MainConfigurationSettingsViewModel.Instance.SystemFilter = CurrentSystemFilter.SystemIDProperty;

            }
        }

        public bool SystemNotChosen
        {
            get { return _systemNotChosen; }
            set
            {
                _systemNotChosen = value;
                OnPropertyChanged("SystemNotChosen");
            }
        }

        public CharacterSheet _selectedNewCharacter;

        public CharacterSheet SelectedNewCharacter
        {
            get { return _selectedNewCharacter; }
            set
            {
                _selectedNewCharacter = value;
                OnPropertyChanged("SelectedNewCharacter");
                CombatService.RosterViewModel.SelectedFullCharacter = value;
                CheckForNameChange();
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }

        #endregion

        internal void SearchForText()
        {
            if (String.IsNullOrWhiteSpace(SearchText))
            {
                ResetActiveList();
                return;
            }
            FilteredCharacters.Clear();
            var matchingList =
                FullRosterBySystem.Where(x => x.Name.ToLower().Contains(SearchText));
            foreach (var cur in matchingList)
            {
                FilteredCharacters.Add(cur);
            }
        }

        public void ResetActiveList()
        {
            if (FullRosterBySystem.Count() != FilteredCharacters.Count())
            {
                FilteredCharacters.Clear();
                foreach (var cur in FullRosterBySystem)
                {
                    FilteredCharacters.Add(cur);
                }
            }
        }

        private IEnumerable<CharacterSheet> FullRosterBySystem
        {
            get
            {
                if (CurrentSystemFilter == _placeholderSystem)
                {
                    return CharacterSheets.FullRoster;
                }
                return
                    CharacterSheets.FullRoster.Where(
                        x => x.Ruleset.Equals(CurrentSystemFilter.SystemIDProperty));
            }
        }
        public ObservableCollection<ISystemConstants> AvailableSystems
        {
            get { return _availableSystems; }
            set { _availableSystems = value; }
        }

        private String _currentCharacterName = "Name";
        private ObservableCollection<ISystemConstants> _availableSystems = new ObservableCollection<ISystemConstants>();
        private ISystemConstants _currentSystemFilter;
        private PlaceholderSystem _placeholderSystem = new PlaceholderSystem();
        private bool _systemNotChosen = true;

        public string CurrentCharacterName
        {
            get
            {
                if (SelectedNewCharacter == null)
                {
                    return _currentCharacterName;
                }
                return _currentCharacterName;
            }
            set
            {
                _currentCharacterName = value;
                OnPropertyChanged("CurrentCharacterName");
            }
        }

        public string SearchText { get; set; }

        private void CheckForNameChange()
        {
            //Set the current name to the default character name if it equals 'name' or if it's empty or if the name matches an existing character name.
            if (IsDefaultName(CurrentCharacterName))
            {
                if (SelectedNewCharacter == null)
                {
                    /* There was a bug where when the first character was selected, the ruleset would be set.
                     * Then the roster would be trimmed of non-usable characters, cleared, and added to available characters.
                     * The selectedcharacter was null during this
                     * And the 'name' was set to 'Name'. Once that changed, the image search was reset, and the 
                     * selected image would be set to null.
                     * Simply, don't change the name in this case.
                     * */
                    //passedCharacterName = "Name";
                }
                else
                {
                    CurrentCharacterName = SelectedNewCharacter.Name;
                }
            }
        }

        internal bool IsDefaultName(string passedCharacterName)
        {
            return passedCharacterName.Equals("Name") ||
                   passedCharacterName.Equals("Image search...") ||
                   String.IsNullOrWhiteSpace(passedCharacterName.Trim()) ||
                   CharacterSheets.FullRoster.Any(x => x.Name.Equals(passedCharacterName));
        }
    }

    internal class PlaceholderSystem : ISystemConstants
    {
        private const string _systemID = "All";
        public string SystemIDProperty
        {
            get { return _systemID; }
        }
        public List<int> GetMovementCircleRadiusList()
        {
            throw new NotImplementedException();
        }

        public SystemService GetSystemService()
        {
            throw new NotImplementedException();
        }

        public double ArrowKeyDistance { get { throw new NotImplementedException(); } }
    }
}